package com.hfb.mashibing.alip8.jvm;

import com.hfb.mashibing.alip8.util.SleepHelper;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

/**
 * java 引用类型：
 *      强/软/弱/虚引用
 *
 * 强引用——new出来的引用
 * 软引用——当内存满时就gc回收。应用场景：缓存
 * 弱引用——每次碰到GC就回收。应用场景：解决内存泄漏、WeakHashMap、ThreadLocal、@Transactional
 * 虚引用——管理队列，拿不倒对象。只能GC调用，GC用来管理堆外内存
 */
public class ReferenceTest {

    static int _10M = 1024 * 1024 * 10;

    public static void main(String[] args) throws InterruptedException {
//        softReference();
//        weakReference();
        phantomReference();
    }

    // 强引用
    // 软引用
    public static void softReference() throws InterruptedException {

        SoftReference<byte[]> sr = new SoftReference<>(new byte[_10M]);

        System.out.println(sr.get());

        System.gc();

        Thread.sleep(500);

        System.out.println(sr.get());

        byte[] bytes = new byte[_10M * 2];

        System.out.println(sr.get());
    }

    // 弱引用
    public static void weakReference() throws InterruptedException {
        System.out.println("weakReference");
        // 虚引用
        WeakReference<byte[]> sr = new WeakReference<>(new byte[_10M]);

        System.out.println(sr.get());

        System.gc();

        Thread.sleep(500);

        System.out.println(sr.get()); // null

        byte[] bytes = new byte[_10M * 2];// java.lang.OutOfMemoryError: Java heap space

        System.out.println(sr.get());
    }

    // 虚引用
    public static void phantomReference() throws InterruptedException {
        System.out.println("phantomReference");

        ReferenceQueue queue = new ReferenceQueue();
        List list = new ArrayList<>();

        PhantomReference<byte[]> sr = new PhantomReference<>(new byte[_10M], queue);

        System.out.println(sr.get()); // null

        ByteBuffer bf = ByteBuffer.allocateDirect(_10M);
        new Thread(()->{
            while(true){
                list.add(new byte[_10M]); // java.lang.OutOfMemoryError: Java heap space
                SleepHelper.sleepMill(1000);
            }
        }).start();

//        System.gc();
//
//        Thread.sleep(500);
//
//        System.out.println(sr.get());
//
//        byte[] bytes = new byte[_10M * 2];

        System.out.println(sr.get()); // null

    }
}
